package com.car.slave.im;

import java.util.List;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

import android.content.Context;
import android.content.Intent;

import com.car.slave.im.model.IMMessage;
import com.car.slave.im.model.command.IMEnterChatMessage;
import com.car.slave.im.model.command.IMLoginMessage;
import com.car.slave.im.model.user.IMAudioMessage;
import com.car.slave.im.model.user.IMImageMessage;
import com.car.slave.im.model.user.IMTextMessage;
import com.car.slave.im.model.user.IMUserMessage;
import com.car.slave.im.receiver.IMLoginReceiver;
import com.car.slave.im.receiver.IMMessageReceiver;
import com.car.slave.im.receiver.IMNotificationReceiver;
import com.car.slave.im.receiver.IMLoginReceiver.InitExceptionStatus;
import com.car.slave.im.receiver.IMLoginReceiver.OnLoginCallback;
import com.car.slave.im.receiver.IMMessageReceiver.OnMessageCallback;
import com.car.slave.im.receiver.IMNotificationReceiver.IMNotificationReceiverCallback;
import com.car.slave.im.util.IMLoginStateUtil;
import com.car.slave.im.util.IMRecentMessage;
import com.car.slave.im.util.IMRecentMessage.IMRecentMessageCallback;

public class IMClient {
	
	private enum LoginState {
		LOGIN_ING,			// 登陆中
		LOGIN_SUCCESS,		// 登陆成功
		LOGIN_FAILED		// 登陆失败
	}
	private LoginState loginState;
	
	// 等待发送的消息队列.
	private BlockingDeque<IMMessage> sendQueue = new LinkedBlockingDeque<IMMessage>();
	
	private boolean messageNotification = true;		// true的时候消息当推送处理，false的时候说明当前正在聊天对话框
	
	private static IMClient sInstance;
	public static synchronized IMClient shareInstance() {
		if (null == sInstance) {
			sInstance = new IMClient();
		}
		return sInstance;
	}
	
	public IMMessage getSendMessage(Context context) throws InterruptedException {
	    // 如果正在登录并且队列里面第一个元素是登陆消息，直接发送出去
		if (loginState == LoginState.LOGIN_ING) {
			IMMessage msg = this.sendQueue.peek();
			if (null != msg && msg instanceof IMLoginMessage) {
				return this.sendQueue.poll(2000, TimeUnit.MILLISECONDS);
			} else {
				Thread.sleep(5000);
				return null;
			}
		}
		// 如果连接服务端失败，继续发送验证信息.
		if (loginState == LoginState.LOGIN_FAILED) {
			Thread.sleep(5000);
			return IMLoginStateUtil.restoreLoginMessage(context);
		}
		// 服务器验证成功
		return this.sendQueue.poll(2000, TimeUnit.MILLISECONDS);
	}
	
	/**
	 * 是否打开消息推送通知.
	 * 如果当前就在聊天界面，可以设置为false来关闭通知.
	 */
	public boolean isMessageNotification() {
		return messageNotification;
	}

	public void setMessageNotification(boolean open) {
		this.messageNotification = open;
	}
	
	/**
	 * 获取用户唯一标示id.
	 * @return
	 */
	public String getUin(Context context) {
		return IMLoginStateUtil.getUin(context);
	}

	/**
	 * 是否已经登陆过.
	 * @return
	 */
	public boolean haveLogined(Context context) {
		if (null == IMLoginStateUtil.restoreLoginMessage(context)) {
			return false;
		}
		return true;
	}
	
	/**
	 * 登陆聊天服务器.
	 * @param context
	 * @param uin					用户唯一ID
	 * @param token 				用于校验用户的合法性
	 * @param clientId 				手机唯一表示符
	 * @param nick
	 * @param pic
	 * @param address
	 * @param clientVer
	 * @param channel
	 */
	public void login(Context context, String uin, String token, String clientId, String nick, String pic, String address,
			String clientVer, String channel) {
		IMLoginMessage loginMsg = new IMLoginMessage(uin, token, clientId, nick, pic, address, clientVer, channel);
		IMLoginStateUtil.saveLoginMessage(context, loginMsg);
	}
	
	/**
	 * 登出聊天服务器.
	 * @param context
	 */
	public void logout(Context context) {
		Intent intent = new Intent(context, IMService.class);
		context.stopService(intent);
		// 清楚本地保存的登陆信息
		IMLoginStateUtil.clearLoginMessage(context);
	}
	
	// 启动后台服务
	private void startServer(Context context) {
		Intent intent = new Intent(context, IMService.class);
		context.startService(intent);
	}
	
	/**
	 * 设置推送的回调.
	 */
	public void setNotificationReceiverCallback(Context context, IMNotificationReceiverCallback callback) {
		System.out.println("设置推送的回调");
		IMNotificationReceiver.receiverCallback = callback;
		startServer(context);
	}

	/**
	 * 初始化Message广播.
	 * @param context
	 * @param messageCallback
	 */
	public void messageCallback(Context context, OnMessageCallback messageCallback) {
		IMClient.shareInstance().setMessageNotification(false);		// 关闭消息推送
		IMMessageReceiver.onRegisterReceiver(context, messageCallback);
		
		this.sendEnterChatMessage();								// 进入聊天框发送消息给服务器
	}
	
	/**
	 * 取消Message广播监听.
	 * @param context
	 */
	public void cancelMessageCallback(Context context) {
		IMClient.shareInstance().setMessageNotification(true);		// 打开消息推送
		IMMessageReceiver.unRegisterReceiver(context);
	}
	
	/**
	 * 获取最近本地聊天记录.
	 * @param context
	 * @param count
	 * @return
	 */
	public List<IMUserMessage> getRecentLocalMessages(Context context, int count) {
		return IMMessageManager.shareInstance(context).getRecentMessages(context, count);
	}
	
	/**
	 * 获取最近聊天记录(分页功能).
	 * @param context
	 * @param count
	 * @param message以上的聊天记录，null的话，就从最近的获取
	 * @param messageCallback 异步获取到消息的回调
	 */
	public void getRecentMessages(Context context, IMUserMessage message, int count, 
			IMRecentMessageCallback messageCallback) {
		IMRecentMessage irm = new IMRecentMessage(messageCallback);
		irm.getRecentMessage(context, message, count);
	}
	
	
	/**
	 * 获取未读消息的数量.
	 * @param context
	 * @return
	 */
	public int getMessageUnReadCount(Context context) {
		return IMMessageManager.shareInstance(context).getUnReadCount(context);
	}
	
	/**
	 * 向服务端发送验证信息.
	 */
	public void sendInitMessage(Context context) {
		this.sendQueue.addFirst(IMLoginStateUtil.restoreLoginMessage(context));
		loginState = LoginState.LOGIN_ING;
		// 注册初始化广播
		IMLoginReceiver.onRegisterReceiver(context, new OnLoginCallback() {
			@Override
			public void onSuccess() {
				loginState = LoginState.LOGIN_SUCCESS;
				System.out.println("服务器登陆成功");
			}
			
			@Override
			public void onFailed(InitExceptionStatus exceptionStatus) {
				System.out.println("服务器登陆失败");
				loginState = LoginState.LOGIN_FAILED;
			}
		});
	}
	
	// 进入聊天框
	private void sendEnterChatMessage() {
		boolean contain = false;
		for (IMMessage msg : this.sendQueue) {
			if (msg instanceof IMEnterChatMessage) {
				contain = true;
				break;
			}
		}
		if (!contain) {
			this.sendQueue.offer(new IMEnterChatMessage());
		}
	}
	
	/**
	 * 发送文本消息.
	 * @param text
	 * @return {@link IMTextMessage}
	 */
	public IMTextMessage sendTextMessage(Context context, String text) {
		IMTextMessage msg = new IMTextMessage(text);
		sendMessage(context, msg);
		return msg;
	}
	
	/**
	 * 发送图片消息.
	 * @param imgPath
 	 * @return {@link IMTextMessage}
	 */
	public IMImageMessage sendImageMessage(Context context, String imgPath) {
		IMImageMessage msg = new IMImageMessage(imgPath);
		sendMessage(context, msg);
		return msg;
	}
	
	/**
	 * 发送语音消息.
	 * @param audioPath
	 * @return {@link IMAudioMessage}
	 */
	public IMAudioMessage sendAudioMessage(Context context, String audioPath) {
		IMAudioMessage msg = new IMAudioMessage(audioPath);
		sendMessage(context, msg);
		return msg;
	}

	/**
	 * 重新发送消息.
	 */
	public void resendMessage(Context context, IMUserMessage message) {
		message.sentStatus = IMUserMessage.STATUS_SENDING;
		this.sendQueue.offer(message);
	}
	
	// 将消息且保存到数据库并且加入到发送队列
	private void sendMessage(Context context, IMUserMessage message) {
		message.markReadStatus();	// 发送给服务端的信息，默认都是已读的.
		IMMessageManager.shareInstance(context).saveMessage(context, message);
		this.sendQueue.offer(message);
	}
}
